package com.craftworks.tiles.impl;

import cn.hutool.core.util.StrUtil;
import com.craftworks.tiles.AbstractTile;

import java.awt.*;
import java.util.List;

public class DigitTile extends AbstractTile
{
    private String digits;
    private String unit;
    private String description;
    private Color digitsColor;
    private Color unitColor;
    private Color descColor;
    private FontMetrics fmDigits;
    private FontMetrics fmUnit;
    private FontMetrics fmDesc;

    private static final Font FONT_DIGITS = new Font("Inter Variable Text", Font.PLAIN, 40);
    private static final Font FONT_UNIT = new Font("Inter Variable Text", Font.PLAIN, 18);
    private static final Font FONT_DESC = new Font("Source Han Sans CN", Font.PLAIN, 16);

    public static DigitTile compact()
    {
        return new DigitTile(Size.LANDSCAPE);
    }

    public static DigitTile wide()
    {
        return new DigitTile(Size.WIDE_LANDSCAPE);
    }

    private DigitTile(Size size)
    {
        super(Size.LANDSCAPE);

        digits = "--";
        unit = "";
        description = "";
        digitsColor = FOREGROUND;
        unitColor = FOREGROUND;
        descColor = FOREGROUND;
    }

    @Override
    public List<String> propertyKeys()
    {
        return List.of("digits", "digits.color", "unit", "unit.color", "desc", "desc.color");
    }

    @Override
    public void setProperty(String key, Object value)
    {
        switch (key)
        {
            case "digits" ->
            {
                switch (value)
                {
                    case null -> digits = "--";
                    case String s -> digits = StrUtil.emptyToDefault(s, "--");
                    case Number n ->
                    {
                        int i = n.intValue();
                        double d = n.doubleValue();
                        digits = ((double) i == d) ? Integer.toString(i) : String.format("%.1f", d);
                    }
                    default -> throw new IllegalStateException("Unexpected value: " + value);
                }
            }
            case "unit" ->
            {
                switch (value)
                {
                    case null -> unit = "";
                    case String s -> unit = s;
                    default -> throw new IllegalStateException("Unexpected value: " + value);
                }
            }
            case "desc" ->
            {
                switch (value)
                {
                    case null -> description = "";
                    case String s -> description = s;
                    default -> throw new IllegalStateException("Unexpected value: " + value);
                }
            }
            case "digits.color" ->
            {
                switch (value)
                {
                    case null -> digitsColor = FOREGROUND;
                    case Color c -> digitsColor = c;
                    case String s -> digitsColor = Color.decode(s);
                    default -> throw new IllegalStateException("Unexpected value: " + value);
                }
            }
            case "unit.color" ->
            {
                switch (value)
                {
                    case null -> unitColor = FOREGROUND;
                    case Color c -> unitColor = c;
                    case String s -> unitColor = Color.decode(s);
                    default -> throw new IllegalStateException("Unexpected value: " + value);
                }
            }
            case "desc.color" ->
            {
                switch (value)
                {
                    case null -> descColor = FOREGROUND;
                    case Color c -> descColor = c;
                    case String s -> descColor = Color.decode(s);
                    default -> throw new IllegalStateException("Unexpected value: " + value);
                }
            }
            default ->
            {
                return;
            }
        }
        repaint();
    }

    @Override
    protected void paintComponent(Graphics g)
    {
        super.paintComponent(g);

        if (fmDigits == null)
            fmDigits = g.getFontMetrics(FONT_DIGITS);
        if (fmUnit == null)
            fmUnit = g.getFontMetrics(FONT_UNIT);
        if (fmDesc == null)
            fmDesc = g.getFontMetrics(FONT_DESC);
        int digitsWidth = fmDigits.stringWidth(digits);
        int unitWidth = fmUnit.stringWidth(unit);
        int descWidth = fmDesc.stringWidth(description);
        if (digitsWidth > size.width - 20)
            digitsWidth = 0; // 超长内容不予显示，下同
        if (unitWidth > size.width / 3)
            unitWidth = 0;
        if (descWidth > size.width - 20)
            descWidth = 0;

        if (digitsWidth == 0 || digitsWidth + 5 + unitWidth > size.width - 20)
            return;

        Graphics2D g2d = (Graphics2D) g;
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);

        // 如果没有描述，就居中对齐；有则靠右对齐。
        int x = (descWidth > 0) ? size.width - (digitsWidth + 5 + unitWidth + 10)
                                : (size.width - (digitsWidth + 5 + unitWidth)) / 2;
        // 如果没有描述，就稍微下沉；有则居中。
        int baseline = (descWidth > 0) ? size.height / 2 : size.height / 2 + fmDigits.getAscent() / 3;

        g2d.setFont(FONT_DIGITS);
        g2d.setPaint(digitsColor);
        g2d.drawString(digits, x, baseline);

        if (unitWidth > 0)
        {
            g2d.setFont(FONT_UNIT);
            g2d.setPaint(unitColor);
            g2d.drawString(unit, x + digitsWidth + 5, baseline);
        }

        if (descWidth > 0)
        {
            baseline = baseline + fmDigits.getDescent() + fmDesc.getAscent();
            g2d.setFont(FONT_DESC);
            g2d.setPaint(descColor);
            g2d.drawString(description, size.width - descWidth - 10, baseline);
        }
    }
}
